using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

namespace SqlBlocks
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Parameters p = new Parameters(Environment.CommandLine);

            Runner.ConnectionString = p["connection"];

            double version = -1;

            if (!double.TryParse(p["version"], out version))
            {
                version = -1;
            }

            MigrationFilter filter = new MigrationFilter
            {
                Version = version,
                Mode = version == -1 ? 
                            MigrationRunMode.Up : version == 0 ? 
                                MigrationRunMode.Down : MigrationRunMode.TargetVersions
            };

            string path = p["path"] ?? Environment.CurrentDirectory;
            Runner.Event += new RunnerEventDelegate(Runner_Event);

            switch (p.Action)
            {
                case "migrate":
                    try
                    {
                        Runner.Run(path, filter);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.StackTrace);
                    }
                    break;
                case "dump":
                    Runner.DumpSchema(p["out"] ?? "schema.sql");
                    break;
                //case "loadschema":
                //    Runner.LoadSchema(p["in"] ?? "schema.sql");
                //    break;
                default:
                    //show help
                    Runner_Event(0, "This is the help file... yay", null);
                    break;
            }
        }

        internal class Parameters
        {
            StringDictionary parameters = new StringDictionary();

            internal Parameters(string raw)
            {
                if (!string.IsNullOrEmpty(raw))
                {
                    string[] args = Environment.GetCommandLineArgs();
                    if (args.Length > 1 && !args[1].StartsWith("/"))
                    {
                        this.action = args[1];
                    }
                    string pattern = @"/(?<arg>((?!/).)*?)(\s*""(?<value>[^""]*)""|\s+(?<value>(?!/).*?)([\s]|$)|(?<value>\s+))";
                    Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
                    MatchCollection matches = regex.Matches(raw);
                    foreach (Match match in matches)
                    {
                        string arg = match.Groups["arg"].Value;
                        string value = match.Groups["value"].Value;
                        parameters.Add(arg, value);
                    }
                }
            }

            private string action = "help";
            public string Action
            {
                get { return action; }
            }

            public string this[string name]
            {
                get { return this.parameters[name]; }
            }
        }

        static int lastDepth = 0;
        static void Runner_Event(int depth, string message, IEnumerable<string> details)
        {
            if (depth == 0)
            {
                Console.WriteLine();
            }
            for (int i = 0; i < depth; i++)
            {
                Console.Write("\t");
            }
            Console.WriteLine(message);

            lastDepth = depth;
            if (details != null)
            {
                foreach (string s in details)
                {
                    Console.WriteLine("\t{0}", s);
                }
            }
        }
    }
}
